package mth.weka.cltree;

import weka.core.Instances;

public class ClusterTreeSplit {
	//calculating the best split for all attributes
	
	private int splitattribute;
	private double splitValue;
	private double returnValue;
	private String splitcriterium;
	private boolean lookahead;
	private boolean binary;
	private int splitPos;
	
	private AttrSplit[] attrSplitter;
	
	public ClusterTreeSplit(String splitcrit, boolean bin) {
		if (splitcrit != null && splitcrit.contains("lookahead-")) {
			splitcrit.replaceAll("lookahead-", "");
			lookahead = true;
		} else {
			lookahead = false;
		}
		splitcriterium = splitcrit;
		binary = bin;
	}
	
	public void calculateBestSplit(Instances newData, Node parent) {
		//TODO: work with binary parameter --> decide based on splitmeasure respectively pass as parameter 
		//TODO: work with splitmeasure parameter --> do so before for-loop (loop is suitable for numeric binary splits)
		//TODO: what about dimensions with low or no best cut? how to define "no best cut"?
		attrSplitter = new AttrSplit[newData.numAttributes()];
		
		int nPoints;
		int yPoints = newData.numInstances();

		if (parent.getNPoints() < newData.numInstances()) {
			nPoints = newData.numInstances();
		} else {
			nPoints = parent.getNPoints();
		}
		
		for (int a=0; a<newData.numAttributes(); a++) {
			newData.sort(a);
			double[] attVal = new double[newData.numInstances()];
			attVal = newData.attributeToDoubleArray(a);
			attrSplitter[a] = new AttrSplit(splitcriterium, lookahead, binary);
			attrSplitter[a].calcBestAttribSplit(attVal, nPoints, yPoints);
		}
		
		double tempMinRd=1.0; //1.0 because everything lower is good. >1.0 shouldn't be possible (RELATIVE density)
		for (int a=0; a<attrSplitter.length; a++) {
			if (tempMinRd > attrSplitter[a].getRd()) {
				tempMinRd = attrSplitter[a].getRd();
				splitValue = attrSplitter[a].getSplitVal();
				splitattribute = a;
				returnValue = attrSplitter[a].getInfogain();
			}
		}
	}

	public int getSplitAttribIndex() {
		return splitattribute;
	}
	
	public double getSplitValue() {
		return splitValue;
	}
	
	public double getInfoGain() {
		return returnValue;
	}
	
	public String getSplitMeasure() {
		return splitcriterium;
	}
	
	public boolean getIsBinarySplit() {
		return binary;
	}
	
	public int getSplitPos() {
		return splitPos;
	}
}
